package net.da.services.spi.local;

import java.util.GregorianCalendar;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import net.da.core.bof.ApplicationSession;
import net.da.core.bof.OrganizationUnit;
import net.da.core.bof.OrganizationUser;
import net.da.core.bof.SysUser;
import net.da.core.dao.OrganisationUserDao;
import net.da.core.exception.DaAuthenticationException;
import net.da.core.exception.DaDatabaseException;
import net.da.core.exception.DaException;
import net.da.core.manager.BusinessObjectManager;
import net.da.services.SecurityService;
import net.da.services.SessionExpiredException;

@Singleton
public class SecurityServiceImpl implements SecurityService {

    private BusinessObjectManager businessObjectManager;
    private OrganisationUserDao organisationUserDao;

    public ApplicationSession authenticateOrganisationUser(String userName, String password,
            String organisationUnit) throws DaException {

        if (userName == null || userName.length() == 0 || password == null || password.length() == 0 ||
                organisationUnit == null || organisationUnit.length() == 0) {
            throw new IllegalArgumentException();
        }

        OrganizationUser organisationUser;
        try {
            organisationUser = organisationUserDao.getOrganisationUser(userName, password, organisationUnit);
        } catch (DaDatabaseException e) {
            throw new DaAuthenticationException(null);
        }

        ApplicationSession applicationSession = businessObjectManager.createBusinessObjectEmptyInstance(ApplicationSession.class);
        applicationSession.setUser(organisationUser);
        applicationSession.setAuthorizationCode("1234567890");
        // 30 min
        applicationSession.setExpirationTime(GregorianCalendar.getInstance());

        // Time factory should be made.
        applicationSession.setLastTime(GregorianCalendar.getInstance());
        applicationSession.save(applicationSession);

        return applicationSession;
    }

    public ApplicationSession authenticateSysUser(String userName, String password) throws DaException  {
        if (userName == null || userName.length() == 0 || password == null || password.length() == 0) {
            throw new IllegalArgumentException();
        }
        SysUser organisationUser;
        try {
            organisationUser = organisationUserDao.getSysUser(userName, password);
        } catch (DaDatabaseException e) {
            throw new DaAuthenticationException(null);
        }

        ApplicationSession applicationSession = businessObjectManager.createBusinessObjectEmptyInstance(ApplicationSession.class);
        applicationSession.setUser(organisationUser);
        applicationSession.setAuthorizationCode("1234567890");
        // 2 hours
        applicationSession.setExpirationTime(GregorianCalendar.getInstance());

        // Time factory should be made.
        applicationSession.setLastTime(GregorianCalendar.getInstance());
        applicationSession.save(applicationSession);

        return applicationSession;
    }


    public OrganizationUnit createNewOrganisationUnit(ApplicationSession session) {
        if (session == null || session.getUser() == null) {
            throw new IllegalArgumentException("Session isn't initialized properly");
        }
        OrganizationUnit organizationUnit = businessObjectManager.createBusinessObjectEmptyInstance(OrganizationUnit.class);
        BusinessObjectCreator.createNewBusinessObject(organizationUnit, session);
        return organizationUnit;
    }

    public OrganizationUser createNewOrganisationUser(ApplicationSession session, OrganizationUnit organizationUnit) {
        if (session == null || session.getUser() == null) {
            throw new IllegalArgumentException("Session isn't initialized properly");
        }
        OrganizationUser organizationUser = businessObjectManager.createBusinessObjectEmptyInstance(OrganizationUser.class);
        BusinessObjectCreator.createNewBusinessObject(organizationUser, session);
        organizationUser.setOrganisationUnit(organizationUnit);
        return organizationUser;
    }

    public SysUser createNewAdminUser() {
        return businessObjectManager.createBusinessObjectEmptyInstance(SysUser.class);
    }

    public OrganizationUnit getOrganisationUnit(Integer id) {
        return businessObjectManager.getBusinessObjectById(OrganizationUnit.class, id);
    }

    @Inject
    public void setBusinessObjectManager(BusinessObjectManager businessObjectManager) {
        this.businessObjectManager = businessObjectManager;
    }

    @Inject
    public void setOrganisationUserDao(OrganisationUserDao organisationUserDao) {
        this.organisationUserDao = organisationUserDao;
    }

    public ApplicationSession authenticateGuestUser() {
        throw new UnsupportedOperationException();
    }

    public ApplicationSession getSessionByAuthorizationCode(String authorisationCode) throws SessionExpiredException {
        throw new UnsupportedOperationException();
    }
}
